﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace CalcSharp.Core.Containers
{
    [Serializable]
    public class DoubleSet: ASet
    {
        private List<double> Storage;
        
        public DoubleSet()
        {
            Storage = new List<double>();
        }

        public DoubleSet(int cnt)
        {
            this.Storage = new List<double>();
            for (int i = 0; i < cnt; i++) this.Storage.Add(double.NaN);
        }

        public DoubleSet(List<double> Existing)
        {
            if (Existing == null) throw new ArgumentNullException("Existing");
            this.Storage = Existing;
        }

        protected override void ValueAt(int index, double value)
        {
            if (index >= 0 && index < Storage.Count) Storage[index] = value;
            else throw new IndexOutOfRangeException();
        }

        protected override double ValueAt(int index)
        {
            if (index >= 0 && index < Storage.Count) return Storage[index];
            else throw new IndexOutOfRangeException();
        }

        public override int Count
        {
            get { return this.Storage.Count; }
        }

        public override double[] ToArray()
        {
            return Storage.ToArray();
        }

        public override bool Contains(double value)
        {
            return this.Storage.Contains(value);
        }

        public override void AddItem(double itm)
        {
            this.Storage.Add(itm);
        }

        public override void DeleteItem(int index)
        {
            this.Storage.RemoveAt(index);
        }

        public override ASet CreateSet(int Count)
        {
            return new DoubleSet(Count);
        }

        public override ASet Randomize()
        {
            Random rgen = new Random();
            List<double> res = this.Storage;
            double tmp;
            int r1, r2;
            for (int i = 0; i < (this.Storage.Count / 2); i++)
            {
                r1 = rgen.Next(0, this.Storage.Count);
                r2 = rgen.Next(0, this.Storage.Count);
                tmp = this.Storage[r1];
                this.Storage[r1] = this.Storage[r2];
                this.Storage[r2] = tmp;
            }
            return new DoubleSet(res);
        }

        public override ASet Unique()
        {
            Dictionary<double, int> dic = new Dictionary<double, int>();
            List<double> res = new List<double>();
            for (int i = 0; i < Storage.Count; i++)
            {
                if (dic.ContainsKey(Storage[i])) dic[Storage[i]]++;
                else dic.Add(Storage[i], 1);
            }
            foreach (double key in dic.Keys)
            {
                if ((dic[key] >= 1) && (!res.Contains(key))) res.Add(key);
            }
            return new DoubleSet(res);
        }

        public override ASet Sort()
        {
            List<double> cpy = Storage;
            cpy.Sort();
            return new DoubleSet(cpy);
        }

        public override ASet Reverse()
        {
            List<double> cpy = this.Storage;
            cpy.Reverse();
            return new DoubleSet(cpy);
        }

        public static DoubleSet operator +(DoubleSet A, DoubleSet B)
        {
            DoubleSet result = new DoubleSet(A.Count + B.Count);
            int i, last;
            for (i = 0; i < A.Count; i++) result[i] = A[i];
            last = A.Count;
            for (i = 0; i < B.Count; i++) result[last + i] = B[i];
            return result;
        } //A unio B

        public static DoubleSet operator /(DoubleSet A, DoubleSet B)
        {
            List<double> temp = new List<double>();
            for (int i = 0; i < A.Count; i++)
            {
                if (!B.Contains(A[i])) temp.Add(A[i]);
            }
            return new DoubleSet(temp);
        } // A külömbség B

        public static DoubleSet operator *(DoubleSet A, DoubleSet B) 
        {
            DoubleSet tmp;
            List<double> its = new List<double>();
            if (A.Count > B.Count) tmp = B;
            else tmp = A;
            for (int i = 0; i < tmp.Count; i++)
            {
                if (A.Contains(i) && B.Contains(i)) its.Add(i);
            }
            return new DoubleSet(its);
        } // A metszet B

        public static DoubleSet operator %(DoubleSet A, DoubleSet B) //A szimetrikus különbség B
        {
            return (A / B) * (B / A);
        }
    }
}
